package com.ham.mud.commands;

import com.ham.mud.Colors;
import com.ham.mud.ServerConnection;
import com.ham.mud.characters.player.Player;
import com.ham.mud.rooms.Exit;
import com.ham.mud.rooms.Room;
import com.ham.mud.rooms.RoomService;

/**
 * Created by hlucas on Jul 19, 2011 at 10:26:43 AM
 */
public class MapCommand extends PlayerCommand {
    public static final String CHAR_PATH = "{D+";
    public static final String CHAR_PATH_TO_ZONE = "{C=";
    public static final String CHAR_PLAYER = "{Y@";
    public static final String CHAR_ROOM = "x";


    final int mapWidth = 20;
    final int mapHeight = 12;
    final int roomsHorizontal = (mapWidth / 4) - 1;
    final int roomsVertical = (mapHeight / 4) - 1;

    @Override
    public void execute(ServerConnection connection, String[] params) {
        connection.println();

        Player player = connection.getPlayer();
        if(player.getVitals().getMove() < 20) {
            connection.println("You're too exhausted to figure out which way is which.");
        } else {
            String[][] map = getEmptyMap();

            Room room = RoomService.getRoom(connection);
            populateMap(map, room);

            drawMap(connection, map);

            player.getVitals().decrementMove(20);
        }

        connection.println();
        connection.showPrompt();
    }

    private String[][] getEmptyMap() {
        String[][] map = new String[mapWidth][mapHeight];

        for(int i = 0; i < mapWidth; i++) {
            for(int j = 0; j < mapHeight; j++) {
                map[i][j] = "{x ";
            }
        }

        for(int i = 1; i < mapHeight - 1; i++) {
            map[0][i] = "{d|";
            map[mapWidth - 1][i] = "{d|";
        }

        for(int i = 1; i < mapWidth - 1; i++) {
            map[i][0] = "{d-";
            map[i][mapHeight - 1] = "{d.";
        }

        map[0][0] = "{d'";
        map[mapWidth - 1][0] = "{d'";
        map[0][mapHeight - 1] = "{d.";
        map[mapWidth - 1][mapHeight - 1] = "{d.";

        return map;
    }

    private void populateMap(String[][] map, Room room) {
        for(int roomY = -roomsVertical, mapY = 0; roomY <= roomsVertical; roomY++, mapY += 2) {
            for(int roomX = -roomsHorizontal, mapX = 0; roomX <= roomsHorizontal; roomX++, mapX += 2) {
                populateRoom(map, room, roomY, mapY, roomX, mapX);
            }
        }
    }

    private void populateRoom(String[][] map, Room room, int roomY, int mapY, int roomX, int mapX) {
        boolean roomExists = RoomService.roomExists(room.getZone(), room.getAtX() + roomX, room.getAtY() + roomY);

        int atX = mapX + 1;
        int atY = mapY + 1;

        boolean inRoom = (roomX == 0 && roomY == 0);


        if(roomExists) {
            if(inRoom) {
                map[atX][atY] = CHAR_PLAYER;
                drawExits(map, room, atX, atY, room);
            } else {
                Room neighbor = RoomService.getRoom(room.getZone(), room.getAtX() + roomX, room.getAtY() + roomY);

                map[atX][atY] = neighbor.getType().getColorString() + CHAR_ROOM;
                drawExits(map, room, atX, atY, neighbor);
            }
        }
    }

    private void drawExits(String[][] map, Room room, int atX, int atY, Room neighbor) {
        if(atX > 1) {
            drawExit(map, room, atX, atY, neighbor, -1, 0);
        }

        if(atX < mapWidth - 2) {
            drawExit(map, room, atX, atY, neighbor, 1, 0);
        }

        if(atY > 1) {
            drawExit(map, room, atX, atY, neighbor, 0, -1);
        }

        if(atY < mapHeight - 2) {
            drawExit(map, room, atX, atY, neighbor, 0, 1);
        }
    }

    private void drawExit(String[][] map, Room room, int atX, int atY, Room neighbor, int dirX, int dirY) {
        Exit exit = neighbor.getExit(dirX, dirY);

        if(exit == null) {
            return;
        }

        if(!map[atX + dirX][atY + dirY].equals("{x ")) {
            return;
        }

        if(exit.getZone() == null || exit.getZone().equals(room.getZone())) {
            map[atX + dirX][atY + dirY] = CHAR_PATH;
        } else {
            map[atX + dirX][atY + dirY] = CHAR_PATH_TO_ZONE;
        }
    }

    private void drawMap(ServerConnection connection, String[][] map) {
        for(int y = mapHeight - 1; y >= 0; y--) {
            for(int x = 0; x < mapWidth; x++) {
                connection.print(map[x][y]);
            }
            connection.println();
        }
        connection.print(Colors.RESET);
    }

    @Override
    protected String getCommandName() {
        return "map";
    }
}
